﻿/*************************************************************************************
 * 文 件 名:   HK_RandomRotOrScale
 * 
 * 描    述:   对选中的物体进行随机旋转和缩放
 * 
 * 版    本：  V1.0
 * 创 建 者：  周阿媛、谭潇杰、京产肠饭
 * 创建时间：  2021/8/29
 * 链   接：  https://gitee.com/JingChanChangFan/hk_-unity-tools
*************************************************************************************/

using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class HK_RandomRotOrScale : EditorWindow
{
    // 是否全局缩放
    bool isGlobalScale = true;

    // 旋转xyz轴锁定
    bool isCanRotX = false;
    bool isCanRotY = true;
    bool isCanRotZ = false;

    // 缩放xyz轴锁定
    bool isCanScaleX = false;
    bool isCanScaleY = false;
    bool isCanScaleZ = false;

    // xyz轴旋转最值
    float rotaY = 360;
    float rotaX = 360;
    float rotaZ = 360;

    // xyz轴缩放最值   
    Vector2 scaleX = Vector2.one;
    Vector2 scaleY = Vector2.one;
    Vector2 scaleZ = Vector2.one;

    // 整体缩放最值
    float scaleMin = 1;
    float scaleMax = 1;

    //选中的物体
    static GameObject[] selectedObjs;

    Dictionary<int, List<Vector3>> InitDataDic = new Dictionary<int, List<Vector3>>();

    Dictionary<int, GameObject> selectObjsDic = new Dictionary<int, GameObject>();

    [MenuItem("HKTools/RandomRotOrScale")]
    static void Init()
    {
        HK_RandomRotOrScale random = GetWindow<HK_RandomRotOrScale>("RandomRotaOrScale");
        random.Show();
    }

    /// <summary>
    /// 随机缩放的EditorGUI绘制
    /// </summary>
    void DrawRandomScaleGUI()
    {
        EditorGUILayout.LabelField("● 随机缩放：", EditorStyles.boldLabel);

        isGlobalScale = EditorGUILayout.ToggleLeft("是否整体随机", isGlobalScale);

        EditorGUILayout.Space(2);

        if (isGlobalScale)
        {
            scaleMin = EditorGUILayout.FloatField("最小缩放倍数:", scaleMin <= 0.01f ? 0.01f : scaleMin);
            scaleMax = EditorGUILayout.FloatField("最大缩放倍数:", scaleMax <= scaleMin ? scaleMin : scaleMax);
        }
        else
        {
            EditorGUILayout.BeginHorizontal();
            isCanScaleX = EditorGUILayout.ToggleLeft("X轴", isCanScaleX, GUILayout.Width(60));
            isCanScaleY = EditorGUILayout.ToggleLeft("Y轴", isCanScaleY, GUILayout.Width(60));
            isCanScaleZ = EditorGUILayout.ToggleLeft("Z轴", isCanScaleZ, GUILayout.Width(60));
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space(2);

            EditorGUI.BeginDisabledGroup(!isCanScaleX);
            scaleX = EditorGUILayout.Vector2Field("X轴缩放倍数 Min&Max：", isCanScaleX ? scaleX : Vector2.one);

            scaleX.x = scaleX.x <= 0.01f ? 0.01f : scaleX.x;
            scaleX.y = scaleX.y <= 0.01f ? 0.01f : scaleX.y;

            scaleX.x = scaleX.x >= scaleX.y ? scaleX.y : scaleX.x;
            scaleX.y = scaleX.y <= scaleX.x ? scaleX.x : scaleX.y;

            EditorGUI.EndDisabledGroup();

            EditorGUI.BeginDisabledGroup(!isCanScaleY);
            scaleY = EditorGUILayout.Vector2Field("Y轴缩放倍数 Min&Max:", isCanScaleY ? scaleY : Vector2.one);

            scaleY.x = scaleY.x <= 0.01f ? 0.01f : scaleY.x;
            scaleY.y = scaleY.y <= 0.01f ? 0.01f : scaleY.y;

            scaleY.x = scaleY.x >= scaleY.y ? scaleY.y : scaleY.x;
            scaleY.y = scaleY.y <= scaleY.x ? scaleY.x : scaleY.y;

            EditorGUI.EndDisabledGroup();

            EditorGUI.BeginDisabledGroup(!isCanScaleZ);
            scaleZ = EditorGUILayout.Vector2Field("Z轴缩放倍数 Min&Max：", isCanScaleZ ? scaleZ : Vector2.one);

            scaleZ.x = scaleZ.x <= 0.01f ? 0.01f : scaleZ.x;
            scaleZ.y = scaleZ.y <= 0.01f ? 0.01f : scaleZ.y;

            scaleZ.x = scaleZ.x >= scaleZ.y ? scaleZ.y : scaleZ.x;
            scaleZ.y = scaleZ.y <= scaleZ.x ? scaleZ.x : scaleZ.y;

            EditorGUI.EndDisabledGroup();
        }

        EditorGUILayout.Space(2);

        if (GUILayout.Button("缩放"))
        {
            if (isGlobalScale)
                SetScaleAll();
            else
                SetScale();
        }
    }

    /// <summary>
    /// 随机旋转的EditorGUI绘制
    /// </summary>
    void DrawRandomRotGUI()
    {
        EditorGUILayout.LabelField("● 随机旋转：", EditorStyles.boldLabel);

        EditorGUILayout.BeginHorizontal();
        isCanRotX = EditorGUILayout.ToggleLeft("X轴", isCanRotX, GUILayout.Width(60));
        isCanRotY = EditorGUILayout.ToggleLeft("Y轴", isCanRotY, GUILayout.Width(60));
        isCanRotZ = EditorGUILayout.ToggleLeft("Z轴", isCanRotZ, GUILayout.Width(60));
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space(2);

        EditorGUI.BeginDisabledGroup(!isCanRotX);
        rotaX = EditorGUILayout.FloatField("X轴+-最大增量", isCanRotX ? rotaX : 360);
        EditorGUI.EndDisabledGroup();

        EditorGUI.BeginDisabledGroup(!isCanRotY);
        rotaY = EditorGUILayout.FloatField("Y轴+-最大增量", isCanRotY ? rotaY : 360);
        EditorGUI.EndDisabledGroup();

        EditorGUI.BeginDisabledGroup(!isCanRotZ);
        rotaZ = EditorGUILayout.FloatField("Z轴+-最大增量", isCanRotZ ? rotaZ : 360);
        EditorGUI.EndDisabledGroup();

        EditorGUILayout.Space(2);

        if (GUILayout.Button("旋转"))
        {
            SetRotate();
        }
    }

    void OnGUI()
    {
        if (Selection.gameObjects.Length > 0)
        {
            for (int i = 0; i < Selection.gameObjects.Length; i++)
            {
                if (!selectObjsDic.ContainsKey(Selection.gameObjects[i].GetInstanceID()))
                {
                    Selection.gameObjects[i].hideFlags = HideFlags.NotEditable;
                    selectObjsDic.Add(Selection.gameObjects[i].GetInstanceID(), Selection.gameObjects[i]);
                }
            }
        }

        EditorGUILayout.Space(10);

        DrawRandomScaleGUI();

        EditorGUILayout.Space(10);

        DrawRandomRotGUI();

        Repaint();
    }

    // 指定轴向随机旋转
    void SetRotate()
    {
        if (Selection.gameObjects.Length == 0)
        {
            Debug.Log("<color=red>错误：</color>" + "没有选中物体！");
            return;
        }

        selectedObjs = Selection.gameObjects;

        for (int i = 0; i < selectedObjs.Length; i++)
        {
            SetInitData(selectedObjs[i].transform);
            Undo.RecordObject(selectedObjs[i].transform, "旋转");
            selectedObjs[i].gameObject.hideFlags = HideFlags.None;

            if (isCanRotX)
                selectedObjs[i].transform.localEulerAngles = new Vector3(
                InitDataDic[selectedObjs[i].transform.GetInstanceID()][0].x + Random.Range(-rotaX, rotaX),
                selectedObjs[i].transform.localEulerAngles.y,
                selectedObjs[i].transform.localEulerAngles.z);

            if (isCanRotY)
                selectedObjs[i].transform.localEulerAngles = new Vector3(
                selectedObjs[i].transform.localEulerAngles.x,
                InitDataDic[selectedObjs[i].transform.GetInstanceID()][0].y + Random.Range(-rotaY, rotaY),
                selectedObjs[i].transform.localEulerAngles.z);

            if (isCanRotZ)
                selectedObjs[i].transform.localEulerAngles = new Vector3(
                selectedObjs[i].transform.localEulerAngles.x,
                selectedObjs[i].transform.localEulerAngles.y,
                Random.Range(-rotaZ, rotaZ) + InitDataDic[selectedObjs[i].transform.GetInstanceID()][0].z);

            selectedObjs[i].gameObject.hideFlags = HideFlags.NotEditable;
        }
    }

    // 指定轴向随机缩放
    void SetScale()
    {
        selectedObjs = Selection.gameObjects;

        if (Selection.gameObjects.Length == 0)
        {
            Debug.Log("<color=red>错误：</color>" + "没有选中物体！");
            return;
        }

        for (int i = 0; i < selectedObjs.Length; i++)
        {
            SetInitData(selectedObjs[i].transform);
            selectedObjs[i].gameObject.hideFlags = HideFlags.None;
            Undo.RecordObject(selectedObjs[i].transform, "缩放");

            if (isCanScaleX)
            {
                float randomValue = Random.Range(scaleX.x, scaleX.y);

                selectedObjs[i].transform.localScale = new Vector3(
                InitDataDic[selectedObjs[i].transform.GetInstanceID()][1].x * randomValue,
                selectedObjs[i].transform.localScale.y,
                selectedObjs[i].transform.localScale.z);
            }

            if (isCanScaleY)
            {
                float randomValue = Random.Range(scaleY.x, scaleY.y);

                selectedObjs[i].transform.localScale = new Vector3(
                selectedObjs[i].transform.localScale.x,
                InitDataDic[selectedObjs[i].transform.GetInstanceID()][1].y * randomValue,
                selectedObjs[i].transform.localScale.z);
            }


            if (isCanScaleZ)
            {
                float randomValue = Random.Range(scaleZ.x, scaleZ.y);

                selectedObjs[i].transform.localScale = new Vector3(
                selectedObjs[i].transform.localScale.x,
                selectedObjs[i].transform.localScale.y,
                InitDataDic[selectedObjs[i].transform.GetInstanceID()][1].z * randomValue);
            }


            selectedObjs[i].gameObject.hideFlags = HideFlags.NotEditable;
        }
    }

    // 整体随机缩放
    void SetScaleAll()
    {
        selectedObjs = Selection.gameObjects;

        if (Selection.gameObjects.Length == 0)
        {
            Debug.Log("<color=red>错误：</color>" + "没有选中物体！");
            return;
        }

        for (int i = 0; i < selectedObjs.Length; i++)
        {
            SetInitData(selectedObjs[i].transform);

            Undo.RecordObject(selectedObjs[i].transform, "缩放");
            selectedObjs[i].gameObject.hideFlags = HideFlags.None;

            float randomValue = Random.Range(scaleMin, scaleMax);

            selectedObjs[i].transform.localScale = new Vector3(
            InitDataDic[selectedObjs[i].transform.GetInstanceID()][1].x * randomValue,
            InitDataDic[selectedObjs[i].transform.GetInstanceID()][1].y * randomValue,
            InitDataDic[selectedObjs[i].transform.GetInstanceID()][1].z * randomValue);

            selectedObjs[i].gameObject.hideFlags = HideFlags.NotEditable;
        }

    }

    //记录选中物体的初始值
    void SetInitData(Transform tf)
    {
        if (!InitDataDic.ContainsKey(tf.GetInstanceID()))
        {
            InitDataDic.Add(tf.GetInstanceID(), new List<Vector3>() { tf.localEulerAngles, tf.localScale });
        }
    }

    void OnDestroy()
    {
        InitDataDic.Clear();

        if (selectObjsDic.Count > 0)
        {
            foreach (KeyValuePair<int, GameObject> item in selectObjsDic)
            {
                item.Value.hideFlags = HideFlags.None;
            }
        }

        selectObjsDic.Clear();
    }
}
